package com.jijuxie.system.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jijuxie.system.domain.SysUser;
import com.jijuxie.system.domain.dto.UserRegisterDTO;
import com.jijuxie.system.domain.dto.UserRegisterResponseDTO;
import com.jijuxie.system.mapper.SysUserMapper;
import com.jijuxie.system.service.IUserRegisterService;
import com.jijuxie.common.exception.ServiceException;
import com.jijuxie.common.utils.RedisCache;
import com.jijuxie.common.utils.SecurityUtils;
import cn.dev33.satoken.stp.StpUtil;

import java.time.LocalDateTime;

@Service
public class UserRegisterServiceImpl implements IUserRegisterService {

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private RedisCache redisCache;

    private static final String VERIFY_CODE_PREFIX = "register:verify:code:";
    private static final long VERIFY_CODE_EXPIRE = 5; // 验证码有效期5分钟

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserRegisterResponseDTO register(UserRegisterDTO registerDTO) {
        // 1. 校验验证码
        String cacheCode = redisCache.getCacheObject(VERIFY_CODE_PREFIX + registerDTO.getPhone());
        if (cacheCode == null || !cacheCode.equals(registerDTO.getVerifyCode())) {
            throw new ServiceException("验证码错误或已过期");
        }

        // 2. 校验用户名、手机号、邮箱是否已存在
        checkUsername(registerDTO.getUsername());
        checkPhone(registerDTO.getPhone());
        checkEmail(registerDTO.getEmail());

        // 3. 校验密码是否一致
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new ServiceException("两次输入的密码不一致");
        }

        // 4. 创建用户
        SysUser user = new SysUser();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(SecurityUtils.encryptPassword(registerDTO.getPassword()));
        user.setNickName(registerDTO.getNickName());
        user.setPhoneNumber(registerDTO.getPhone());
        user.setEmail(registerDTO.getEmail());
        user.setAvatar(registerDTO.getAvatar());
        user.setSex(registerDTO.getSex());
        user.setStatus("0"); // 正常状态
        user.setDelFlag("0"); // 未删除
        user.setLoginIp("");
        user.setLoginDate(LocalDateTime.now());
        user.setRoleId(2L); // 普通用户角色ID

        userMapper.insert(user);

        // 5. 清除验证码
        redisCache.deleteObject(VERIFY_CODE_PREFIX + registerDTO.getPhone());

        // 6. 生成登录令牌
        StpUtil.login(user.getUserId());
        String token = StpUtil.getTokenValue();
        long tokenExpireTime = StpUtil.getTokenTimeout();

        // 7. 返回结果
        return UserRegisterResponseDTO.builder()
                .userId(user.getUserId())
                .username(user.getUsername())
                .nickName(user.getNickName())
                .token(token)
                .tokenExpireTime(tokenExpireTime)
                .build();
    }

    @Override
    public boolean sendVerifyCode(String phone) {
        // 1. 校验手机号格式
        if (!phone.matches("^1[3-9]\\d{9}$")) {
            throw new ServiceException("手机号格式不正确");
        }

        // 2. 生成6位随机验证码
        String verifyCode = String.format("%06d", (int) (Math.random() * 1000000));

        // 3. 将验证码保存到Redis，设置5分钟过期
        redisCache.setCacheObject(VERIFY_CODE_PREFIX + phone, verifyCode, VERIFY_CODE_EXPIRE);

        // 4. 发送验证码短信
        // TODO: 调用短信服务发送验证码
        
        return true;
    }

    @Override
    public boolean checkUsername(String username) {
        if (userMapper.selectCountByUsername(username) > 0) {
            throw new ServiceException("用户名已存在");
        }
        return true;
    }

    @Override
    public boolean checkPhone(String phone) {
        if (userMapper.selectCountByPhone(phone) > 0) {
            throw new ServiceException("手机号已被注册");
        }
        return true;
    }

    @Override
    public boolean checkEmail(String email) {
        if (userMapper.selectCountByEmail(email) > 0) {
            throw new ServiceException("邮箱已被注册");
        }
        return true;
    }
} 